package com.s63.modules.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Slf4j
@Configuration
//启用@PreAuthorize注解鉴权
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private TokenFilter tokenFilter;

    // 使用spring security提供的随机盐算法对密码进行hash
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 在LoginService中使用该bean
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 从数据库查询用户以及对应的权限
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 关闭csrf保护，前后端分离项目不需要
        http.csrf().disable();
        // 无状态session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // api配置
        http.authorizeRequests()
                // 所有人可以访问的api
                .antMatchers("/swagger*/**",
//                        "/swagger-resources/**",
                        "/v3/api-docs",
                        "/webjars/**",
                        "/doc.html", "/login", "/logout").permitAll()
                // 其他api都需要登录后访问
                .anyRequest().authenticated();
        // 异常处理
        http.exceptionHandling()
            // 认证失败(登录失败或无效token)
            .authenticationEntryPoint((request, response, authException) -> response.setStatus(401))
            // 授权失败
            .accessDeniedHandler((request, response, accessDeniedException) -> response.setStatus(403));
        // 添加自定义token过滤器到spring security的UsernamePasswordAuthenticationFilter过滤器之前
        http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
